/******************************************************************************
 *  Copyright (c) 2016, Xilinx, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  1.  Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *  2.  Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 *  3.  Neither the name of the copyright holder nor the names of its
 *      contributors may be used to endorse or promote products derived from
 *      this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 *  OR BUSINESS INTERRUPTION). HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 *  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/
/******************************************************************************
 *
 *
 * @file pmod_pwm.c
 *
 * IOP code (MicroBlaze) for Pmod Timer.
 * Pulses can be generated by the Pmod timer.
 * The timer can also detect pulses on the Pmod pin.
 * The input / output pin is assumed to be at Pin 1 of any Pmod.
 * Since the AXI TmrCtr IP's device driver does not support PWM, 
 * the pulses are generated using low-level driver calls.
 * setupTimers() function is used. 
 * pmod_init() function is not called, because IIC and SPI are not used.
 *
 * <pre>
 * MODIFICATION HISTORY:
 *
 * Ver   Who  Date     Changes
 * ----- --- ------- -----------------------------------------------
 * 1.00a pp  05/10/16 release
 * 1.00b yrq 05/27/16 clean up the codes
 * 1.00c yrq 08/08/16 change coding style
 *
 * </pre>
 *
 *****************************************************************************/

#include "circular_buffer.h"
#include "xio_switch.h"
#include "timer.h"


// Mailbox commands
#define CONFIG_IOP_SWITCH       0x1
#define GENERATE                0x3
#define STOP                    0x5

/*
 * TIMING_INTERVAL = (TLRx + 2) * AXI_CLOCK_PERIOD
 * PWM_PERIOD = (TLR0 + 2) * AXI_CLOCK_PERIOD
 * PWM_HIGH_TIME = (TLR1 + 2) * AXI_CLOCK_PERIOD
 */

/*
 * Parameters passed in MAILBOX_WRITE_CMD
 * bits 31:16 => period in us
 * bits 15:8 is not used
 * bits 7:1 => duty cycle in %, valid range is 1 to 99
 */

/************************** Function Prototypes ******************************/
static timer device;

int main(void) {
    u32 cmd;
    u32 Timer1Value, Timer2Value;
    u32 pwm_pin;

    /*
     * Configuring Pmod IO switch
     * bit-0 is controlled by the pwm
     */
    device = timer_open_device(0);
    init_io_switch();

    while(1){
        while(MAILBOX_CMD_ADDR==0);
        cmd = MAILBOX_CMD_ADDR;
        
        switch(cmd){
            case CONFIG_IOP_SWITCH:
                // read new pin configuration
                pwm_pin = MAILBOX_DATA(0);
                set_pin(pwm_pin, PWM0);
                MAILBOX_CMD_ADDR = 0x0;
                break;
                  
            case GENERATE:
                Timer1Value = (MAILBOX_DATA(0) & 0x0ffff) *100;
                Timer2Value = (MAILBOX_DATA(1) & 0x07f)*Timer1Value/100;
                timer_pwm_generate(device, Timer1Value, Timer2Value);
                MAILBOX_CMD_ADDR = 0x0;
                break;
                
            case STOP:
                timer_pwm_stop(device);
                MAILBOX_CMD_ADDR = 0x0;
                break;
            
            default:
                MAILBOX_CMD_ADDR = 0x0;
                break;
        }
    }
    return 0;
}

